#!/bin/sh

usage () {
	cat <<EOF>&2
Usage: ${0##*/} [OPTIONS] SEARCH REPLACE [FILES]

Replace SEARCH by REPLACE in FILES. If no file is provided, use stdin.
Backslashes are interpreted in SEARCH and REPLACE (e.g. \n, \t). If you want to
inhibit this behaviour, you need to double them.

Options:

  -h:  Show this help.
  -i:  Replace file content instead of printing to stdout.

EOF
}

OPT_INPLACE=""
while getopts ":ih" opt; do
	case $opt in
	i)
		OPT_INPLACE=-i ;;
	h)
		usage
		exit 1 ;;
	\?)
		usage
		exit 1 ;;
	esac
done

shift $((OPTIND - 1))

if [ $# -lt 2 ]; then
	usage
	exit 1
fi

search="$1"
replace="$2"
shift 2

replace () {
	## We cannot use gsub, otherwise regex substitutions could occur.
	## Source: http://mywiki.wooledge.org/BashFAQ/021
	awk -v s="$search" -v r="$replace" 'BEGIN {l=length(s)} {o="";while (i=index($0, s)) {o=o substr($0,1,i-1) r; $0=substr($0,i+l)} print o $0}' "$@"
}

if [ $# -eq 0 ] || [ -z "$OPT_INPLACE" ]; then
	replace "$@"
else
	for i ; do
		out="$(mktemp "$i.XXXXXX")"
		replace "$i" > "$out"
		mv "$out" "$i"
	done
fi
